---
title: Query Definition
description:
  Implement the first GraphQL object types and fields that provide the functionality of a Hacker
  News
---

import { Callout } from '@theguild/components'

# A Simple Query

In this section, you are going to implement the first GraphQL object types and fields that provide
the functionality of a Hacker News clone for querying a feed of _links_ that were posted by other
users.

## Extending the Schema Definition

Let's start by implementing a `feed` field on the `Query` root types which allows retrieving a list
of `Link` elements. In general, when adding a new feature to the GraphQL Schema, the process will
look pretty similar every time:

1. Extend the GraphQL schema definition (SDL) with new _root fields_ (on the `Query`, `Mutation` or
   `Subscription` object types) and new _object types_ and fields, if needed
2. Implement corresponding _resolver functions_ for the added fields/object types

This process is also referred to as the _schema-driven_ or _schema-first development_ workflow.

So, let's go ahead and tackle the first step, extending the GraphQL schema definition.

In `src/schema.ts`, update the GraphQL schema to look as follows:

```ts filename="src/schema.ts"
const typeDefinitions = /* GraphQL */ `
  type Query {
    info: String!
    feed: [Link!]!
  }

  type Link {
    id: ID!
    description: String!
    url: String!
  }
`
```

Pretty straightforward, right? You're defining a new `Link` object type that represents the links
that can be posted to Hacker News. Each `Link` entity has an `id`, a `description`, and a `url`
field. You're then adding another field to the root `Query` type that allows you to retrieve a list
of `Link` elements. This list is guaranteed to never be `null` (if there isn't anything, the list
must be empty) and never contain any elements that are `null` - that's what the two exclamation
marks are for.

<Callout>
  If you wish to read more about GraphQL and nullability, go ahead to [GraphQL official
  documentation](https://graphql.org/learn/schema/#lists-and-non-null).
</Callout>

## Implement Resolver Functions

The next step is to implement the resolver function for the `feed` query field. One thing we haven't
mentioned yet is that not only _root fields_, but virtually _all_ fields on the types in a GraphQL
schema have resolver functions. So, you'll add resolver functions for the `id`, `description`, and
`url` fields of the `Link` type as well.

In `src/schema.ts`, add a new list with dummy data as well and update the `resolvers` to look as
follows:

```ts filename="src/schema.ts"
// 1
type Link = {
  id: string
  url: string
  description: string
}

// 2
const links: Link[] = [
  {
    id: 'link-0',
    url: 'https://graphql-yoga.com',
    description: 'The easiest way of setting up a GraphQL server'
  }
]

const resolvers = {
  Query: {
    info: () => `This is the API of a Hackernews Clone`,
    // 3
    feed: () => links
  },
  // 4
  Link: {
    id: (parent: Link) => parent.id,
    description: (parent: Link) => parent.description,
    url: (parent: Link) => parent.url
  }
}
```

Let's walk through the numbered comments again:

1. The `Link` type defines the TypeScript object structure that we wish to use in our code
2. The `links` variable is used to store the links at runtime. For now, everything is stored only
   _in-memory_ rather than being persisted in a database
3. You're adding a new resolver for the `feed` root field. Notice that a resolver always has to be
   named _exactly_ after the corresponding field from the schema definition
4. Finally, you're adding three more resolvers for the fields on the `Link` type from the schema
   definition. We'll discuss what the `parent` argument that's passed into the resolver here is in a
   bit

Go ahead and test the implementation by running the server and navigating to
`http://localhost:4000/graphql` in your browser. If you expand the documentation of the GraphiQL,
you'll notice that another field on the root `Query` object type called `feed` is now available:

![another `Query` root type field called feed](/assets/tutorial/basic/05-a-simple-mutation/feed-link-query-response.png)

Try it out by sending the following query operation via GraphiQL:

```graphql
query {
  feed {
    id
    url
    description
  }
}
```

Awesome, the server responds with the data you defined in `links`:

```json
{
  "data": {
    "feed": [
      {
        "id": "link-0",
        "url": "https://graphql-yoga.com",
        "description": "The easiest way of setting up a GraphQL server"
      }
    ]
  }
}
```

Feel free to play around with the query by removing any fields from the selection set and observing
the responses sent by the server.

### The Query Resolution Process

Let's now quickly talk about how a GraphQL server resolves incoming requests. As you already saw, a
GraphQL operation contains a selections set of _fields_ that have their source in the type
definitions of the GraphQL schema.

Let's consider the following query operation from above again:

```graphql
query {
  feed {
    id
    url
    description
  }
}
```

All four fields specified in the query operation's selection set (`feed`, `id`, `url`, and
`description`) can also be found inside the schema definition. You also learned that _every_ field
inside the schema definition is backed by one resolver function whose responsibility it is to return
the data for precisely that field.

Can you imagine what the query resolution process looks like now? Effectively, the GraphQL server
has to invoke all resolver functions for the fields that are selected in the operation and then
package up the response according to the selection set's shape. The resolution thus merely becomes a
process of orchestrating the invocation of the resolver functions!

Right now all the resolvers for the `Link` type follow a very simple and trivial pattern:

```js
Link: {
  id: (parent: Link) => parent.id,
  description: (parent: Link) => parent.description,
  url: (parent: Link) => parent.url
}
```

First, it's important to note that every GraphQL resolver function receives _four_ input arguments.
As the remaining three are not needed in our scenario right now, we're simply omitting them. Don't
worry, you'll get to know them soon.

The first argument, commonly called `parent` (or sometimes `root`) is the result of the previous
_resolver execution level_. Hang on, what does that mean? 🤔

Well, as you already saw, GraphQL operation selection sets can be _nested_. Each level of nesting
(i.e. nested curly braces) corresponds to one resolver execution level. Therefore, the above query
operation has two of these execution levels.

On the first level, it invokes the `Query.feed` resolver and returns the entire data stored in
`links`. For the second execution level, the GraphQL server is smart enough to invoke the resolvers
of the `Link` type (because thanks to the schema, it knows that `feed` returns a list of `Link`
elements) for each element inside the list that was returned on the previous resolver level.
Therefore, in all the three `Link` resolvers, the incoming `parent` object is the element inside the
`links` list.

<Callout>
  Note: To learn more about this, check out
  [this](https://www.prisma.io/blog/graphql-server-basics-the-schema-ac5e2950214e#9d03) article.
</Callout>

<Callout>
  The implementation of the `Link` resolvers is trivial, you can omit them and the server will work
  in the same way as it did before 👌. We just wanted you to understand what's happening under the
  hood 🚗.
</Callout>
